﻿using System.Text;
using System;
using System.Windows;
namespace DeepEarth.Map.Core.Utilities
{
    public class TileSourceUtility
    {
        public static string TileXYToQuadKey(int tileX, int tileY, int levelOfDetail)
        {
            var quadKey = new StringBuilder();
            for (int i = levelOfDetail; i > 0; i--)
            {
                char digit = '0';
                int mask = 1 << (i - 1);
                if ((tileX & mask) != 0)
                {
                    digit++;
                }
                if ((tileY & mask) != 0) 
                {
                    digit++;
                    digit++;
                }
                quadKey.Append(digit);
            }
            return quadKey.ToString();
        }

        // zoomlevel is the bing map zoom level, not the multiscaleimage level of detail
        public static Rect TileXYZoomToLogicalRect(int tileX, int tileY, int zoomLevel)
        {
            double width = 1.0 / Math.Pow(2, zoomLevel);

            Point topLeft = new Point(tileX * width, tileY * width);
            Point bottomRight = new Point((tileX + 1) * width, (tileY + 1) * width);

            return new Rect(topLeft, bottomRight);
        }
        
      
    }

    public class XYZTilePath
    {
        private string xFragment = "{x}";
        private string yFragment = "{y}";
        private string zFragment = "{z}";

        public string XFragment
        {
            get { return xFragment; }
            set { xFragment = value; }
        }

        public string YFragment
        {
            get { return yFragment; }
            set { yFragment = value; }
        }

        public string ZFragment
        {
            get { return zFragment; }
            set { zFragment = value; }
        }

        public string UriFormat { get; set; }

        public string GetUri(int tileLevel, int tilePositionX, int tilePositionY)
        {
            if (!UriFormat.Contains(XFragment) && !UriFormat.Contains(YFragment) && !UriFormat.Contains(ZFragment))
            {
                throw new Exception("URI Format does not contain any replacement sequences");
            }

            string uri = UriFormat;
            uri = uri.Replace(XFragment, tilePositionX.ToString());
            uri = uri.Replace(YFragment, tilePositionY.ToString());
            uri = uri.Replace(ZFragment, tileLevel.ToString());

            return uri;
        }
    }

    public class QuadKeyTilePath
    {
        const string DEFAULT_QUADKEY_FRAGMENT = "{quadkey}";

        private string quadkeyUriFragment = DEFAULT_QUADKEY_FRAGMENT;
        public string QuadKeyUriFragment
        {
            get
            {
                return quadkeyUriFragment;
            }
            set
            {
#if !WINDOWS_PHONE
                if (!string.IsNullOrWhiteSpace(value))
#else
                if (!string.IsNullOrEmpty(value.Trim()))
#endif                
                {
                    quadkeyUriFragment = value;
                }
            }
        }

        const string DEFAULT_SUBDOMAIN_FRAGMENT = "{subdomain}";

        private string subdomainUriFragment = DEFAULT_SUBDOMAIN_FRAGMENT;
        public string SubdomainUriFragment
        {
            get
            {
                return subdomainUriFragment;
            }
            set
            {
#if !WINDOWS_PHONE
                if (!string.IsNullOrWhiteSpace(value))
#else
                if (!string.IsNullOrEmpty(value.Trim()))
#endif  
                {
                    subdomainUriFragment = value;
                }
            }
        }

        const string DEFAULT_CULTURE_FRAGMENT = "{culture}";

        private string cultureUriFragment = DEFAULT_CULTURE_FRAGMENT;
        public string CultureUriFragment
        {
            get
            {
                return cultureUriFragment;
            }
            set
            {
#if !WINDOWS_PHONE
                if (!string.IsNullOrWhiteSpace(value))
#else
                if (!string.IsNullOrEmpty(value.Trim()))
#endif  
                {
                    cultureUriFragment = value;
                }
            }
        }

        public string UriFormat { get; set; }
        public string Culture { get; set; }

        public string GetUri(int tileLevel, int tilePositionX, int tilePositionY)
        {
            var quadKey = TileSourceUtility.TileXYToQuadKey(tilePositionX, tilePositionY, tileLevel);
            var subdomain = quadKey.Substring(quadKey.Length - 1, 1);
            return UriFormat.Replace(QuadKeyUriFragment, quadKey).Replace(SubdomainUriFragment, subdomain).Replace(CultureUriFragment, Culture);
        }
    }

    public class LambdaFilePath
    {
        public Func<int, int, int, string> Formatter { get; set; }

        public string GetUri(int tileLevel, int tilePositionX, int tilePositionY)
        {
            return Formatter(tileLevel, tilePositionX, tilePositionY);
        }
    }
}
